/* 
 * File:   maplayer.c
 * Author: bjorn
 *
 * Created on September 2, 2007, 9:16 PM
 */

#include <SDL/SDL.h>
#include "maplayer.h"
#include "memory.h"
#include "screen.h"
#include "image.h"

#define MAPLAYER_TILES_MAX 10000
#define MAPLAYER_WIDE_MAX 1000
#define MAPLAYER_HIGH_MAX 1000


eruta_struct(Terraintile) {
  signed char high;
  Terrainkind kind;
};

eruta_struct(Terrainlayer){
    struct Terraintile_struct layer[MAPLAYER_HIGH_MAX][MAPLAYER_WIDE_MAX];
    Terrainhigh        water_high;
    Terrainhigh        ground_high;
};

eruta_struct(Maplayer) {
    Image _tiles[MAPLAYER_TILES_MAX];
    Image _layer[MAPLAYER_HIGH_MAX][MAPLAYER_WIDE_MAX];
    Terrainlayer terrain;
    long wide;
    long high;
    long tilecount;
    int  tilewide;
    int  tilehigh;
};

Terrainlayer terrainlayer_make(long wide, long high) {
    Terrainlayer result; 
    (void) wide;     (void) high;

    result = memory_make(Terrainlayer);
    return result;
}

Terrainlayer terrainlayer_free(Terrainlayer self) {
    memory_free(self);
    return NULL;
}

Terraintile terrainlayer_get(Terrainlayer self, int x, int y) {
    return &self->layer[x][y];
}

Maplayer maplayer_make(long wide, long high) {
    Maplayer result; 
	  if(wide>MAPLAYER_WIDE_MAX) return NULL;
    if(high>MAPLAYER_HIGH_MAX) return NULL;
    result = eruta_make(Maplayer);
    result->wide = wide;
    result->high = high;
    result->tilewide = MAPLAYER_TILE_WIDE;
    result->tilehigh = MAPLAYER_TILE_HIGH;
    result->tilecount = 0;
    result->terrain = terrainlayer_make(wide, high);
    return result;
}

Maplayer maplayer_wipe(Maplayer self) {
    terrainlayer_free(self->terrain);    
    memory_free(self->_tiles);
    memory_free(self);
    return NULL;
}

Terrainlayer maplayer_terrain(Maplayer self) {
  return self->terrain;
}


int maplayer_add(Maplayer self, Image tile) {
    int result = self->tilecount;
    self->_tiles[result] = tile;
    self->tilecount++;
    return result;    
}

Maplayer maplayer_set(Maplayer self, int x, int y, int tile_id) {
    self->_layer[x][y] = self->_tiles[tile_id];
    return self;
}

Image maplayer_get(Maplayer self, int x, int y) {
    return self->_layer[x][y];
}

Maplayer maplayer_draw(Maplayer self, Screen screen, int x, int y ) {  
        int txstart = ( x / self->tilewide );
        int tystart = ( y / self->tilehigh );
        int _xtilestop  = (screen_wide(screen) / self->tilewide) + 1 ;
        int _ytilestop  = (screen_high(screen) / self->tilehigh) + 1 ;        
        int txstop = _xtilestop + txstart;
        int tystop = _ytilestop + tystart;
        int drawx  = 0;
        int drawy  = 0;
		int txdex  ;
		int tydex  ;
        Image *row;
        Image aidimage = NULL;

        if (txstart >= self->wide || tystart >= self->high) { 
            return self;
        } 
        if (txstart < 0) txstart = 0;
        if (tystart < 0) tystart = 0;
        if  (txstop >= self->wide) txstop = self->wide;
        if  (tystop >= self->high) tystop = self->high;        
        
        drawx = -x + ( (txstart-1) * self->tilewide );

        for (txdex = txstart; txdex < txstop; txdex ++ ) {
            drawx   += self->tilewide;            
            drawy   = -y + ( (tystart-1) * self->tilehigh );
            row     = self->_layer[txdex];            
            if(row == NULL) continue;
            
            for (tydex = tystart; tydex < tystop; tydex ++ ) {                
                aidimage    = row[tydex];                
                if(aidimage == NULL) continue;
                /* Get the tile. If it is null, immediately skip to the next tile. */
                drawy   += self->tilehigh;                
                /* The tile rendered can never be completely off screen. */
                screen_blit(screen, drawx, drawy, aidimage);                
            }
        
        }
        return self;
}
